<?php

namespace app\models;

use app\components\BaseActiveRecord;
use app\helpers\AppHelper;
use app\helpers\EmailHelper;
use app\helpers\EncryptHelper;
use Cassandra\Exception\ValidationException;
use http\Exception\RuntimeException;
use Yii;
use yii\db\Exception;
use yii\helpers\ArrayHelper;
use yii\web\IdentityInterface;
use yii\web\UserEvent;

/**
 * This is the model class for table "{{%users}}".
 *
 * @property int $id
 * @property int $gid
 * @property string $username
 * @property string $nickname
 * @property string $password
 * @property string $avatar
 * @property string $email
 * @property int $credit
 * @property string $token
 * @property int $last_login_time
 * @property int $last_login_ip
 * @property int $status
 * @property int $create_time
 */
class User extends BaseActiveRecord implements IdentityInterface {

    const GROUP_MEMBER = 1;
    const GROUP_MEMBER_VIP = 2;

    const STATUS_IN_ACTIVE = 1;
    const STATUS_ACTIVE = 2;
    const STATUS_DISABLED = 3;

    const rememberTime = 3600 * 24 * 365;

    public $rememberMe = TRUE;

    public $newPwd;
    public $newPwd2;
    public $password2;
    public $captcha;
    public $emailCode;

    public $statusLabels = [];

    public static $groupLabels = [
        self::GROUP_MEMBER => '普通会员',
        self::GROUP_MEMBER_VIP => 'VIP会员',
    ];

    public function init() {
        parent::init();
        $this->newPwd = $this->password2 = '';
        $this->status = static::STATUS_IN_ACTIVE;
        $this->gid = self::GROUP_MEMBER;
        $this->on(\yii\web\User::EVENT_AFTER_LOGIN, [$this, 'afterLogin']);

        $this->statusLabels = [
            self::STATUS_DISABLED => Yii::t('app', 'Disabled'),
            self::STATUS_ACTIVE => Yii::t('app', 'Active'),
            self::STATUS_IN_ACTIVE => Yii::t('app', 'InActive'),
        ];
    }

    /**
     * @inheritdoc
     */
    public static function tableName() {
        return '{{%user}}';
    }

    /**
     * @inheritdoc
     */
    public function rules() {
        $rules = [
            [['gid', 'credit', 'last_login_time', 'last_login_ip', 'status', 'create_time'], 'integer'],
            [['username', 'nickname', 'avatar', 'email'], 'string', 'max' => 120],
            [['password'], 'string', 'max' => 16],
            [['email'], 'email'],
            [['token'], 'string', 'max' => 160],
        ];

        $rules[] = [['username', 'password'], 'required', 'on' => 'login'];
        $rules[] = [['username', 'email'], 'unique', 'on' => 'register'];
        $rules[] = [['username', 'password', 'gid', 'email'], 'required', 'on' => 'register'];
//        $rules[] = [['captcha'], 'captcha', 'on' => 'register'];
//        $rules[] = [['captcha'], 'captcha', 'on' => 'login'];
//        $rules[] = [['password'], 'compare', 'compareAttribute' => 'password2', 'on' => 'register'];
        return $rules;
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels() {
        $attributeLabels = [
            'id' => Yii::t('app', 'ID'),
            'gid' => Yii::t('app', 'Gid'),
            'username' => Yii::t('app', 'Username'),
            'nickname' => Yii::t('app', 'Nickname'),
            'password' => Yii::t('app', 'Password'),
            'avatar' => Yii::t('app', 'Avatar'),
            'email' => Yii::t('app', 'Email'),
            'credit' => Yii::t('app', 'Credit'),
            'token' => Yii::t('app', 'Token'),
            'last_login_time' => Yii::t('app', 'Last Login Time'),
            'last_login_ip' => Yii::t('app', 'Last Login Ip'),
            'status' => Yii::t('app', 'Status'),
            'create_time' => Yii::t('app', 'Create Time'),
        ];

        $attributeLabels['rememberMe'] = Yii::t('app', 'Remember Me');
        $attributeLabels['newPwd2'] = Yii::t('app', 'Confirm New Password');
        $attributeLabels['password2'] = Yii::t('app', 'Confirm Password');
        $attributeLabels['newPwd'] = Yii::t('app', 'New Password');
        $attributeLabels['emailCode'] = Yii::t('app', 'Email Verification Code');
        $attributeLabels['captcha'] = Yii::t('app', 'Captcha');
        return $attributeLabels;
    }

    public function fields() {
        $fields = parent::fields();
        $fields['avatar'] = function ($model) {
            return AppHelper::formatImage($model['avatar']);
        };
        return $fields;
    }

    public static function findIdentity($id) {
        return self::findOne($id);
    }

    public static function findIdentityByAccessToken($token, $type = NULL) {
        // TODO: Implement findIdentityByAccessToken() method.
    }

    public function getId() {
        return $this->id;
    }

    public function getAuthKey() {
        return EncryptHelper::md5(APP_KEY);
    }

    public function getGroupName() {
        return ArrayHelper::getValue(static::$groupLabels, $this->gid);
    }

    public function getStatusName() {
        return ArrayHelper::getValue($this->statusLabels, $this->status);
    }

    public function validateAuthKey($authKey) {
        return EncryptHelper::md5(APP_KEY) === $authKey;
    }

    public function isActive() {
        return intval($this->status) === self::YES;
    }

    public function isDisable() {
        return intval($this->status) === self::NO;
    }


    public function login() {
        try {
            $this->validate();

            $user = static::findOne(['username' => $this->username]);
            if (!$user) {
                return static::retErr(Yii::t('app', 'Username or password is incorrect.'));
            }
            $_pass = EncryptHelper::md5($this->password);
            if ($_pass !== $user['password']) {
                return static::retErr(Yii::t('app', 'Username or password is incorrect.'), 1, [$_pass, $user->password, APP_KEY]);
            }

            if (!$user->isActive()) {
                return static::retErr(Yii::t('app', 'Account is disabled.'));
            }

            $this->id = $user->id;
            $this->loginCookie($user);

//            $this->updateFavorite(self::getUid());
        } catch (\Exception $e) {
            return static::retErr($e->getMessage());
        }
        return static::retOK();
    }

    protected function updateFavorite($uid) {
        UserHistory::updateAll(['uid' => $this->id], ['uid' => $uid]);
        UserFavorite::updateAll(['uid' => $this->id], ['uid' => $uid]);
        UserScore::updateAll(['uid' => $this->id], ['uid' => $uid]);
    }

    /**
     * @param null $attributeNames
     * @param bool $clearErrors
     * @return bool|void
     * @throws Exception
     */
    public function validate($attributeNames = NULL, $clearErrors = TRUE) {
        $v = parent::validate($attributeNames, $clearErrors);
        if (!$v) {
            throw new Exception($this->getError());
        }
        return $v;
    }

    public function register() {
        try {
            $this->validate();

            $this->password = EncryptHelper::md5($this->password);
            $this->avatar = $this->generateAvatar();

            $this->save();

            $this->loginCookie();

            $this->afterLogin(new UserEvent(['identity' => $this]));

            return static::retOK($this->id, Yii::t('app', 'registration success'));
        } catch (\Exception $e) {
            return static::retErr($e->getMessage());
        }
    }


    /**
     * @param UserEvent $event
     * @throws Exception
     */
    public function afterLogin(UserEvent $event) {
        /* @var $user User */
        $user = $event->identity;
        if (!$user->getIsNewRecord()) {
            $user->last_login_ip = AppHelper::getClientIp();
            $user->last_login_time = time();
            $user->token = EncryptHelper::encode(uniqid(time()));
            $user->save();
        }
    }

    public function loginCookie(IdentityInterface $identity = NULL) {
        if (NULL === $identity) {
            $identity = $this;
        }
        Yii::$app->user->login($identity, $this->rememberMe ? self::rememberTime : 0);
    }

    public function getAvatar() {
        return empty($this['avatar']) ? Yii::getAlias('@theme/images/avatar.jpg') : AppHelper::formatImage($this['avatar']);
    }

    public function generateAvatar() {
        $api = "https://comment.mkzcdn.com/comment/?comic_id=215041&page_num=1&page_size=50";
        for ($i = 0; $i < 5; $i++) {
            $data = file_get_contents($api, 0, stream_context_create(['http' => ['timeout' => 5]]));
            $data = json_decode($data, TRUE);
            if (isset($data['code']) && intval($data['code']) === 200) {
                $list = $data['data']['list'];
                $k = array_rand($list);
                return "{$list[$k]['avatar']}!cover-200";
            }
        }
        return '';
    }
}
